package com.htgd.gardenexpo.service.impl;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.htgd.gardenexpo.dao.GeConSportsMaxMapper;
import com.htgd.gardenexpo.dao.WxUserDao;
import com.htgd.gardenexpo.entity.CommonResult;
import com.htgd.gardenexpo.entity.GeConSportsMax;
import com.htgd.gardenexpo.entity.WxUser;
import com.htgd.gardenexpo.page.WxUserQuery;
import com.htgd.gardenexpo.service.DeviceService;
import com.htgd.gardenexpo.service.WxUserService;
import com.htgd.gardenexpo.utils.TokenUtil;
import com.htgd.gardenexpo.utils.WeChatUtils;
import com.htgd.gardenexpo.vo.UserNumVO;
import com.htgd.gardenexpo.vo.WxUserVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.htgd.gardenexpo.utils.SelectHomePlaceUtils.getPhoneNumAttribution;

@Service
public class WxUserServiceImpl extends ServiceImpl<WxUserDao, WxUser> implements WxUserService {

    @Autowired
    private  WxUserDao wxUserDao;

    @Value("${local.url}")
    public String local_url;

    @Value("${wx.public.appId}")
    public String appId;

    @Value("${wx.public.appsecret}")
    public String appsecret;

    @Value("${device.editUser_url}")
    public String editUserUrl;

    @Value("${device.unbindFace_url}")
    public String unbindFaceUrl;


    @Autowired
    private DeviceService deviceService;

    @Autowired
    private WeChatUtils weChatUtils;

    @Autowired
    private GeConSportsMaxMapper geConSportsMaxMapper;
    @Override
    public Object getPhoneNumber(Map<String, Object> data) {
        String phone = "";
        //通过appid和secret来获取token
        //WXContent.APPID是自定义的全局变量
        String tokenUrl = String.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", appId, appsecret);
        JSONObject token = JSON.parseObject(HttpUtil.get(tokenUrl));

        //通过token和code来获取用户手机号
        String url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + token.getString("access_token");

        //封装请求体
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("code", data.get("code").toString());

        //封装请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

        HttpEntity<Map<String, String>> httpEntity = new HttpEntity<>(paramMap,headers);

        //通过RestTemplate发送请求，获取到用户手机号码
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<Object> response = restTemplate.postForEntity(url, httpEntity, Object.class);

        // 从 ResponseEntity 中获取响应体
        Object responseBody = response.getBody();

//        // 将响应体转换为包含手机号信息的对象
//        if (responseBody instanceof Map && ((Map<?, ?>) responseBody).size()>2) {
//            Map<String, Object> responseMap = (Map<String, Object>) responseBody;
//            Map<String, Object> phoneInfoMap = (Map<String, Object>) responseMap.get("phone_info");
//            phone = (String) phoneInfoMap.get("phoneNumber");
//
//            //新增用户
//            WxUser wxUser = new WxUser();
//            wxUser.setPhone(phone);
//            wxUser.setName(phone);
//            wxUser.setUrl(local_url+"head/moren.jpeg");
//
//
//            GeBaseUser geBaseUser = new GeBaseUser();
//            geBaseUser.setPhone(phone);
//            String sign = TokenUtil.sign(geBaseUser);
//
//            wxUser.setToken(sign);
//
//            wxUserDao.insert(wxUser);
//
//            responseMap.put("wxUser",wxUser);
//            return responseMap;
//        }else {
//
//            //返回到前端展示
//            return response.getBody();
//        }
        return response.getBody();

    }

    @Override
    public String getOpenId(String code) {
        String params = "appid=" + appId + "&secret=" + appsecret + "&js_code=" + code + "&grant_type=" + "authorization_code";
        String url = "https://api.weixin.qq.com/sns/jscode2session?"+params;

        RestTemplate restTemplate = new RestTemplate();

        String response = restTemplate.getForObject(url, String.class);

        JSONObject jsonObject = JSON.parseObject(response);
        String openid = jsonObject.getString("openid");

        return openid;
    }

    @Override
    public String getSessionKey(String code) {
        String params = "appid=" + appId + "&secret=" + appsecret + "&js_code=" + code + "&grant_type=" + "authorization_code";
        String url = "https://api.weixin.qq.com/sns/jscode2session?"+params;

        RestTemplate restTemplate = new RestTemplate();

        String response = restTemplate.getForObject(url, String.class);

        JSONObject jsonObject = JSON.parseObject(response);
        String sessionKey = jsonObject.getString("session_key");
        return sessionKey;
    }

    @Override
    @Transactional
    public WxUser login(String openId) {
        WxUser wxUser1 = lambdaQuery().eq(WxUser::getOpenId, openId).one();
        if(wxUser1==null){
            //新增用户
            WxUser wxUser = new WxUser();
            wxUser.setUrl(local_url+"head/moren.jpeg");
            wxUser.setName("微信用户");
            wxUser.setOpenId(openId);
            wxUser.setCreateTime(LocalDateTime.now());
            wxUser.setCouponNum(0);
            wxUser.setCarbonNum(0);
            wxUser.setIntegralNum(10000);
            wxUser.setFace("0");
            wxUserDao.insert(wxUser);
//            carbonMobileTask.addUser(wxUser);
            GeConSportsMax geConSportsMax = new GeConSportsMax();
            geConSportsMax.setOpenId(openId);
            geConSportsMax.setMaxCalorie("0");
            geConSportsMax.setMaxDuration("0");
            geConSportsMax.setMaxMileage("0");
            geConSportsMaxMapper.insert(geConSportsMax);
            return wxUserDao.selectById(wxUser.getUserId());
        }else {
            GeConSportsMax one = geConSportsMaxMapper.selectOne(new LambdaQueryWrapper<GeConSportsMax>().eq(GeConSportsMax::getOpenId, openId));
            if(one==null){
                GeConSportsMax geConSportsMax = new GeConSportsMax();
                geConSportsMax.setOpenId(openId);
                geConSportsMax.setMaxCalorie("0");
                geConSportsMax.setMaxDuration("0");
                geConSportsMax.setMaxMileage("0");
                geConSportsMaxMapper.insert(geConSportsMax);
            }
            return wxUser1;
        }
    }

    @Override
    @Transactional
    public CommonResult bindPhone(JSONObject jsonObject) {
        //获取用户id
        String userId = jsonObject.getString("userId");

        //获取手机号
        Object phoneNumber = getPhoneNumber(jsonObject);
        String phoneNumberStr = JSON.toJSONString(phoneNumber); // 将对象转换为JSON字符串
        JSONObject jsonObject1 = JSONObject.parseObject(phoneNumberStr);
        JSONObject phone_info = jsonObject1.getJSONObject("phone_info");
        String phoneNumber1 = phone_info.getString("phoneNumber");

        if(phoneNumber1!=null){
            //获取号码归属地
            String city = getPhoneNumAttribution(phoneNumber1);

            //更新甲板信息
            try{
                //更新用户信息
                lambdaUpdate()
                        .eq(WxUser::getUserId,userId)
                        .set(WxUser::getPhone,phoneNumber1)
                        .set(WxUser::getCity,city)
                        .update();
                return CommonResult.success("手机号更新成功",phoneNumber1);
            }catch (Exception e){
                System.out.println(e);
                return CommonResult.error("手机号更新失败：错误-"+e);
            }
        }else {
            return CommonResult.error("手机号更新失败：获取手机号信息错误-"+phoneNumber);
        }

    }

    @Override
    public void updateToken(String token, WxUser wxUser) {
        lambdaUpdate().eq(WxUser::getOpenId,wxUser.getOpenId())
                .set(WxUser::getToken,token)
                .update();
    }

    @Override
    public String getPhoneByOpenId(String openId) {
        return lambdaQuery().eq(WxUser::getOpenId,openId)
                .select(WxUser::getPhone)
                .one() // 假设只查询到一个结果
                .getPhone();
    }

    @Override
    public String getNameByOpenId(String openId) {
        return lambdaQuery().eq(WxUser::getOpenId,openId)
                .select(WxUser::getName)
                .one()
                .getName();
    }

    @Override
    public PageInfo<WxUserVO> querylist(WxUserQuery wxUserQuery) {
        PageHelper.startPage(wxUserQuery.getPageNum(),wxUserQuery.getPageSize());
        List<WxUserVO> wxUserVOS = wxUserDao.querylist(wxUserQuery);
        for (WxUserVO wxUserVO : wxUserVOS) {
            wxUserVO.setKey(wxUserVO.getUserId());
        }
        return new PageInfo<>(wxUserVOS);
    }

    @Override
    public boolean judgePhoneIsNullByOpenId(String openId) {
        return lambdaQuery().eq(WxUser::getOpenId,openId)
                .select(WxUser::getPhone)
                .exists();
    }

    @Override
    public UserNumVO getNum(String openId) {
        return wxUserDao.getNum(openId);
    }

    @Override
    public void updateCarbonNumAdd(Integer num, String openId) {
        wxUserDao.updateCarbonNumAdd(num,openId);
    }

    @Override
    public void updateIntegralNumAdd(Integer num, String openId) {
        wxUserDao.updateIntegralNumAdd(num,openId);

    }

    @Override
    public WxUser getInfo(HttpServletRequest request) {
        String accessToken = request.getHeader("Access_token");
        String openId = TokenUtil.getUsernameFromToken(accessToken);
        return wxUserDao.selectOne(new LambdaQueryWrapper<WxUser>().eq(WxUser::getOpenId,openId));
    }

    @Override
    public CommonResult getRegisterNums(String date) {
        Map<String,Object> map = new HashMap<>();
        DateTimeFormatter formatter =  DateTimeFormatter.ofPattern("yyyy-MM-dd");

        //不传，默认当天
        if(date==null||"".equals(date)){
            date = LocalDateTime.now().format(formatter);
        }

        //按日期查
        Long count = wxUserDao.getNumByDate(date);
        map.put("count",count);

        //总数
        Long totalCount = lambdaQuery().count();
        map.put("totalCount",totalCount);

        return CommonResult.success("查询成功",map);
    }

    @Override
    public CommonResult getPhoneCityNums() {
        List<Map<String,Object>> map = wxUserDao.getPhoneCityNums();
        return CommonResult.success("成功",map);
    }

    @Override
    public CommonResult bindFace(JSONObject body) {
        //获取甲板id
        String userId = body.getString("userId");
        if(userId==null){
            return CommonResult.error("userId为必传参数");
        }
        boolean exists = lambdaQuery().eq(WxUser::getDeckId, userId).exists();
        if(!exists){
            return CommonResult.error("该用户不存在");
        }

        //更新人脸信息
        lambdaUpdate().eq(WxUser::getDeckId,userId)
                .set(WxUser::getFace,"1")
                .set(WxUser::getFaceTime,LocalDateTime.now())
                .update();
        return CommonResult.success("人脸绑定成功");
    }

    @Override
    public void updateDeckId(String openId, String userId) {
        //获取用户信息
        WxUser one = lambdaQuery().eq(WxUser::getOpenId, openId).one();

        //更新甲板id
        if(one!=null){
            lambdaUpdate().eq(WxUser::getOpenId,openId)
                    .set(WxUser::getDeckId,userId)
                    .update();
        }
    }

    @Override
    @Transactional
    public CommonResult<JSONObject> edit(WxUser wxUser) {

        try {
            if(wxUser.getSex()!=null){
                if (!"1".equals(wxUser.getSex()) && !"2".equals(wxUser.getSex())) {
                    return CommonResult.error("性别值非法");
                }
            }
            //更新
            wxUserDao.updateById(wxUser);

            //获取信息
            WxUser one = lambdaQuery().eq(WxUser::getUserId, wxUser.getUserId()).one();

            //甲板更新
            RestTemplate restTemplate = new RestTemplate();

            // 构建请求头
            HttpHeaders headers = new HttpHeaders();
            headers.set("Authorization", "Bearer "+deviceService.deviceLogin());  // 设置认证 token 或其他头部
            headers.setContentType(MediaType.APPLICATION_JSON);

            // 构建请求体
            JSONObject body = new JSONObject();
            body.put("userId",one.getDeckId());
            body.put("avatar",one.getUrl());
            body.put("nickName",one.getName());
            body.put("username",one.getDeckId());
            if(one.getSex()!=null){
                body.put("sex",Integer.parseInt(one.getSex())-1);
            }
            if(one.getAge()!=null){
                body.put("age",one.getAge());
            }
            if(one.getHeight()!=null){
                body.put("height",one.getHeight());
            }if(one.getWeight()!=null){
                body.put("weight",one.getWeight());
            }
            System.out.println("body:"+body);

            // 创建 HttpEntity，将请求体和请求头一起封装
            HttpEntity<JSONObject> entity = new HttpEntity<>(body, headers);

            // 发送 PUT 请求
            ResponseEntity<JSONObject> response = restTemplate.exchange(
                    editUserUrl,
                    HttpMethod.PUT,
                    entity,
                    JSONObject.class);  // 123 是路径参数（ID）

            JSONObject responseBody = response.getBody();
            System.out.println(responseBody);
//            if(!"0".equals(responseBody.getString("code"))){
//                return CommonResult.error("更新用户信息失败：甲板报错-"+responseBody);
//            }
            return CommonResult.success("更新成功");
        }catch (Exception e){
            System.out.println(e);
            return CommonResult.success("更新成功");
        }

    }

    @Override
    public CommonResult getDailyActivityCount(String beginDate, String endDate) {
        HashMap<String, Object> map = new HashMap<>();
        long num = 0;
        JSONObject dailyActivityCount = weChatUtils.getDailyActivityCount(beginDate, endDate);
        JSONArray visit_uv = dailyActivityCount.getJSONArray("visit_uv");
        for (Object o : visit_uv) {
            JSONObject  object= JSONObject.parseObject(o.toString());
            if(object.getInteger("key")==0){
                num=object.getInteger("value");
                break;
            }
        }
        map.put("num",num);
        return CommonResult.success("查询成功",map);
    }

    @Override
    @Transactional
    public CommonResult unbindFace(String openId) {
        //获取甲板id
        String deckId = wxUserDao.getDeckId(openId);
        if(deckId==null){
            return CommonResult.error("该用户甲板id不存在");
        }
        //甲板注销人脸
        try{
            RestTemplate restTemplate = new RestTemplate();
            // 构建请求头
            HttpHeaders headers = new HttpHeaders();
            headers.set("Authorization", "Bearer "+deviceService.deviceLogin());  // 设置认证 token 或其他头部
            headers.setContentType(MediaType.APPLICATION_JSON);
            // 构建请求体
            Long[] face = new Long[1];
            face[0] = Long.valueOf(deckId);
            // 创建 HttpEntity，将请求体和请求头一起封装
            HttpEntity< Long[]> entity = new HttpEntity<>(face, headers);
            System.out.println("body："+entity);

            // 发送 PUT 请求
            ResponseEntity<JSONObject> response = restTemplate.exchange(
                    unbindFaceUrl,
                    HttpMethod.DELETE,
                    entity,
                    JSONObject.class);  // 123 是路径参数（ID）

            JSONObject responseBody = response.getBody();
            if(responseBody==null ||  0!=responseBody.getInteger("code")){
                return CommonResult.error("甲板注销用户失败："+responseBody);
            }

        }catch (Exception e){
            System.out.println(e);
            return CommonResult.error("甲板注销用户失败："+e);
        }

        //更新人脸状态
        lambdaUpdate().eq(WxUser::getOpenId,openId)
                .set(WxUser::getFace,0)
                .update();
        return CommonResult.success("人脸解绑成功");
    }

}
